package miage.rest;

import miage.rest.security.SimpleEnroler;
import java.util.HashMap;
import java.util.Map;
import miage.rest.resource.candidature.CandidatResource;
import miage.rest.resource.candidature.CandidatureResource;
import miage.rest.resource.candidature.CandidaturesResource;
import miage.rest.resource.candidature.NationalitesResource;
import miage.rest.resource.candidature.SessionResource;
import miage.rest.resource.candidature.StatutResource;
import miage.rest.resource.candidature.StatutsResource;
import miage.rest.resource.misc.StatsResource;
import miage.rest.security.Roles;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.MediaType;
import org.restlet.representation.StringRepresentation;
import org.restlet.routing.Router;
import org.restlet.routing.TemplateRoute;
import org.restlet.routing.Variable;
import org.restlet.security.Authenticator;
import org.restlet.security.ChallengeAuthenticator;
import org.restlet.security.Verifier;

/**
 *
 * @author smith
 */
public class Application extends org.restlet.Application {

    private static final String authenticationRealm = "Service Web MIAGE";

	
	private final Router router;

	private final Verifier verifier;
	

    public Application(Router router, Verifier verifier) {
        this.router = router;
		this.verifier = verifier;

		setupRoles();
    }

    @Override
    public synchronized Restlet createInboundRoot() {

		Restlet inboundRoot = null;

		router.setContext(getContext());

		/**
		 * Stats ressource
		 */
		router.attach("/stats", StatsResource.class);

		/**
         * Informations concernant un candidat
         */
        router.attach("/candidats/{idCandidat}", CandidatResource.class);

        /**
         * Information concernant une candidature
         */
        router.attach("/candidatures/{idCandidature}", CandidatureResource.class);

        /**
         * Liste des candidatures à une session
         */
        router.attach("/sessions/{idSession}/candidatures", CandidaturesResource.class);

        /**
         * L'ensemble des status que peut avoir une candidature
         */
        router.attach("/candidatures/statuts", StatutsResource.class);

        /**
         * Modification du statut d'une cadidature
         */
        router.attach("/candidatures/{idCandidature}/statut", StatutResource.class);

        /**
         * Information et modification d'une session
         * GET et PUT
         */
        router.attach("/sessions/{idSession}" , SessionResource.class);

		/**
         * Emettre une candidature pour une session
         * POST /sessions/{idSession}/candidats/{idCandidat}/candidatures
         */
        router.attach("/sessions/{idSession}/candidats/{idCandidat}/candidatures", SessionResource.class);


		/**
         * Liste des nationalités
         * GET /nationalites
         */
        router.attach("/nationalites", NationalitesResource.class);


		 /**
         * Rappel du mot de passe
         * POST /candidats/{idCandidat}/rappels
         */

		for(TemplateRoute route : router.getRoutes()) {
			route.getTemplate().setVariables(getVariables());
		}

		
        Restlet mainpage = new Restlet() {

            @Override
            public void handle(Request request, Response response) {
                StringBuilder stringBuilder = new StringBuilder();

                stringBuilder.append("<html>");
                stringBuilder.append("<head><title>PPD REST</title></head>");
                stringBuilder.append("<body>");
                stringBuilder.append("<h1>Page d'accueil &mdash; PPD REST</h1>");
                stringBuilder.append("</body>");
                stringBuilder.append("</html>");

                response.setEntity(new StringRepresentation(stringBuilder.toString(), MediaType.TEXT_HTML));

            }
        };
		
        router.attach("/", mainpage);

		//Si une instance de verifier a été fourni on place le filtre d'authentification
		//On ajoute notre routeur à la suite du filtre d'authentification
		if (verifier != null) {
			Authenticator authenticator = getNewAuthenticator();
			authenticator.setNext(router);
			inboundRoot = authenticator;
		} else {
			inboundRoot = router;
		}

        return inboundRoot;
    }

	private Map<String, Variable> getVariables() {
		Map<String, Variable> variables = new HashMap<String, Variable>();

		variables.put("idSession", new Variable(Variable.TYPE_DIGIT));
		variables.put("idCandidat", new Variable(Variable.TYPE_DIGIT));
		variables.put("idCandidature", new Variable(Variable.TYPE_DIGIT));

		return variables;
	}

	/**
	 * Renvoie une nouvelle instance d'un filtre d'authentification
	 * Le filtre renvoyé permet aux utilisateurs de s'authentifier via la classe
	 * de type Verifier
	 * en utilisant la méthode HTTP Basic Auth
	 *
	 * @param domainReference
	 * @return
	 */
	private Authenticator getNewAuthenticator() {

		ChallengeAuthenticator authenticator = new ChallengeAuthenticator(
				this.getContext(),
				false,
				ChallengeScheme.HTTP_BASIC,
				authenticationRealm
		);

		authenticator.setVerifier(verifier);
		authenticator.setEnroler(new SimpleEnroler());

		return authenticator;
	}

	private void setupRoles() {

		this.getRoles().add(Roles.ADMIN);
		this.getRoles().add(Roles.ANONYMOUS);
		this.getRoles().add(Roles.CANDIDAT);

	}
}
